<?php
/**
 * @author jonathan poelen <jonathan.poelen@gmail.com>
 * @version 1.0: jo_link_noir
 * @date 05-06-2010
 */
abstract class SW_Resource_DAO extends SW_DAO implements SW_Resource_DAO_Interface
{
	const DEFAULT_TABLE_STRUCTURE = 'resource';


	/** @var string : nom de la table ressource*/
	protected $tableResource;

	/** @var string : référence de la table ressource vers la table structure*/
	protected $refStructure;

	/** @var string : référence vers la table des planète*/
	protected $refPlanet;


	/**
	 * @param string $tableResource = self::DEFAULT_TABLE_STRUCTURE
	 * @param string $refStructure
	 * @param string $refPlanet = null
	 * @param PDO $pdo = null : si null alors = SW_DAO::getDB()
	 */
	public function __construct($tableResource = self::DEFAULT_TABLE_STRUCTURE, $refStructure, $refPlanet = null, PDO $pdo = null)
	{
		$this->tableResource =  '`'.$tableResource.'`';
		$this->refStructure =  '`'.$refStructure.'`';
		$this->refPlanet =  '`'.$refPlanet.'`';
		parent::__construct($pdo);
	}

	/**
	 * @param int $id_structure
	 * @param int $group
	 * @param int $quantity
	 * @param int $time_end
	 * @param int $id_planet
	 * @return SW_Resource_Element
	 */
	protected function newElement($id_structure, $group, $quantity, $time_end, $id_planet)
	{
		return new SW_Resource_Element($id_structure, $group, $quantity, $time_end);
	}

	/**
	 * @param int $id_planet
	 * @param int $id_structure
	 * @param int $group
	 * @param int $quantity
	 * @param int $time_end
	 * @return SW_Resource_Element
	 */
	public function create($id_planet, $id_structure, $group, $quantity, $time_end)
	{
		$this->insert($id_planet, $id_structure, $group, $quantity, $time_end);
		return $this->newElement($id_structure, $group, $quantity, $time_end, $id_planet);
	}

	/**
	 * @param int $id_planet
	 * @param int $id_structure
	 * @param int $group
	 * @param int $quantity
	 * @param int $time_end
	 */
	protected function insert($id_planet, $id_structure, $group, $quantity, $time_end)
	{
		if (!isset(self::$queries[__METHOD__]))
			$this->prepare(__METHOD__,
				'INSERT INTO '.$this->tableResource.'('.$this->refPlanet.', '.$this->refStructure.', `group`, quantity, time_end) VALUES(?,?,?,?,?)'
			);

		self::$queries[__METHOD__]->execute(
			array($id_planet, $id_structure, $group, $quantity, $time_end)
		);
	}

	/**
	 * @param array|SW_Resource_Element $element
	 */
	public function update($elements)
	{
		if (!isset(self::$queries[__METHOD__]))
			$this->prepare(__METHOD__,
				'UPDATE '.$this->tableResource.' SET quantity=?, time_end=? WHERE '.$this->refStructure.'=?'
			);

		foreach (($elements instanceof SW_Resource_Element) ? array($elements) : $elements as $element)
		{
			self::$queries[__METHOD__]->execute(
				array($element->getQuantity(), $element->getTimeEnd(), $element->getId())
			);
		}
	}

	/**
	 * @param array $resource : {id => int}
	 * @attention cette méthode ne modifie pas les éléments. Utilisé SW_Resource::decrease ou SW_Resource::increase
	 */
	public function increaseQuantities(array $quantities)
	{
		if (!isset(self::$queries[__METHOD__]))
			$this->prepare(__METHOD__,
				'UPDATE '.$this->tableResource.' SET quantity=quantity+(?) WHERE '.$this->refStructure.'=?'
			);

		foreach ($quantities as $ref => $count)
			self::$queries[__METHOD__]->execute(
				array($count, $ref)
			);
	}

	/**
	 * @param array $resource : {id => int}
	 * @attention cette méthode ne modifie pas les éléments utilisé SW_Resource::decrease ou SW_Resource::increase
	 */
	public function decreaseQuantities(array $quantities)
	{
		if (!isset(self::$queries[__METHOD__]))
			$this->prepare(__METHOD__,
				'UPDATE '.$this->tableResource.' SET quantity=quantity-(?) WHERE '.$this->refStructure.'=?'
			);

		foreach ($quantities as $ref => $count)
			self::$queries[__METHOD__]->execute(
				array($count, $ref)
			);
	}

	/**
	 * Modifie les ressources en base sans prendre en compte le changement des éléments
	 * @param int $id_planet
	 * @param array $resource : {id => quantity}
	 * @attention Vu que cette méthode ne modifie pas les éléments s'ils ne l'ont pas été leurs quantités de ressource sera fausse
	 */
	public function increaseResource($id_planet, array $resources)
	{
		if (!isset(self::$queries[__METHOD__]))
			$this->prepare(__METHOD__,
				'UPDATE '.$this->tableResource.' SET quantity=quantity+(?) WHERE `group`=? AND ref_planet=?'
			);

		foreach ($resources as $id => $quantity)
		{
			self::$queries[__METHOD__]->execute(
				array($quantity, $id, $id_planet)
			);
		}
	}

	/**
	 * Sélectionne les ressources d'une planète
	 * @param int $id_planet
	 * @return array : {id => U1_Resource_Element, ...}
	 */
	public function selectAllInPlanet($id_planet)
	{
		if (!isset(self::$queries[__METHOD__]))
			$this->prepare(__METHOD__,
				'SELECT '.$this->refStructure.' as id, `group`, quantity, time_end FROM '.$this->tableResource.' WHERE ref_planet=?'
			);

		self::$queries[__METHOD__]->bindParam(1, $id_planet, PDO::PARAM_INT);
		self::$queries[__METHOD__]->execute();

		$resources = array();
		while ($r = self::$queries[__METHOD__]->fetchObject())
			$resources[$r->id] = $this->newElement($r->id, $r->group, $r->quantity, $r->time_end, $id_planet);
		return $resources;
	}

	/**
	 * Sélectionne les ressources de toutes les planètes d'un joueur
	 * @param int $id_user
	 * @param string $tablePlanet = null
	 * @param string $ref_user = null
	 * @return array : {id_planet => {id => U1_Resource_Element, ...}, ...}
	 */
	public function selectAll($id_user, $tablePlanet = null, $ref_user = null)
	{
		$id_user = (int)$id_user;
		$sth = $this->pdo->query(
			'SELECT _p.id as id_planet, _r.'.$this->refStructure.' as id, `group`, quantity, time_end FROM '.$this->tableResource.' as _r
			JOIN `'.$tablePlanet.'` as _p ON _p.`'.$ref_user.'`='.$id_user,
			PDO::FETCH_OBJ
		);

		$resources = array();
		while ($r = $sth->fetchObject())
			$resources[$r->id_planet][$r->id] = $this->newElement($r->id, $r->group, $r->quantity, $r->time_end, $r->id_planet);

		return self::$resourcesUser[$id_user];
	}
}